#include <sstream>

#include "foldedtorus.hpp"
#include "booksim.hpp"
#include "random_utils.hpp"
#include "misc_utils.hpp"
#include "globals.hpp"

vector<vector<vector<int>>> global_routing_table2;

FoldedTorus::FoldedTorus(const Configuration &config,
                         const string &name) :
    Network(config, name) {
    _ComputeSize(config);
    _Alloc();
    _BuildNet(config);

    router_id = {
        {16, 0, 1, 2, 3, 20},
        {17, 4, 5, 6, 7, 21},
        {18, 8, 9, 10, 11, 22},
        {19, 12, 13, 14, 15, 23},
    };

    side_nodes = {
        16, 17, 18, 19,
        20, 21, 22, 23};

    links_to_this_router = {
        {3, 26, 72, 48},
        {0, 30, 49, 76},
        {4, 34, 80, 51},
        {1, 38, 50, 84},
        {5, 42, 52, 88},
        {2, 46, 53, 92},

        {9, 27, 74, 54},
        {6, 31, 55, 78},
        {10, 35, 57, 82},
        {7, 39, 86, 56},
        {11, 43, 58, 90},
        {8, 47, 59, 94},

        {15, 24, 73, 60},
        {12, 28, 77, 61},
        {16, 32, 81, 63},
        {13, 36, 85, 62},
        {17, 40, 89, 64},
        {14, 44, 93, 65},

        {21, 25, 75, 66},
        {18, 29, 79, 67},
        {22, 33, 69, 83},
        {19, 37, 68, 87},
        {23, 41, 70, 91},
        {20, 45, 71, 95}};

    links_from_this_router = {
        {24, 0, 74, 51},
        {28, 1, 78, 48},
        {32, 3, 82, 52},
        {36, 2, 49, 86},
        {40, 4, 90, 53},
        {44, 5, 50, 94},

        {6, 26, 57, 75},
        {7, 30, 54, 79},
        {9, 34, 83, 58},
        {8, 38, 55, 87},
        {10, 42, 59, 91},
        {11, 46, 56, 95},

        {12, 25, 72, 63},
        {13, 29, 60, 76},
        {15, 33, 64, 80},
        {14, 37, 61, 84},
        {16, 41, 65, 88},
        {17, 45, 62, 92},

        {18, 27, 73, 69},
        {19, 31, 77, 66},
        {21, 35, 81, 70},
        {20, 39, 85, 67},
        {22, 43, 89, 71},
        {23, 47, 93, 68}};

    routing_table = {
        {
            {0},
            {0, 16, 1},
            {0, 2},
            {0, 16, 1, 3},
            {0, 4},
            {0, 16, 1, 5},
            {0, 4, 6},
            {0, 16, 17, 5, 7},
            {0, 8},
            {0, 16, 1, 9},
            {0, 8, 10},
            {0, 16, 18, 9, 11},
            {0, 8, 12},
            {0, 8, 12, 19, 13},
            {0, 2, 10, 14},
            {0, 16, 1, 3, 11, 15},
            {0, 16},
            {0, 4, 17},
            {0, 8, 18},
            {0, 16, 18, 19},
            {0, 2, 20},
            {0, 2, 20, 21},
            {0, 2, 20, 22},
            {0, 8, 12, 14, 23},
        },
        {
            {1, 16, 0},
            {1},
            {1, 16, 0, 2},
            {1, 3},
            {1, 16, 0, 4},
            {1, 5},
            {1, 16, 17, 4, 6},
            {1, 5, 7},
            {1, 16, 0, 8},
            {1, 9},
            {1, 16, 18, 8, 10},
            {1, 9, 11},
            {1, 9, 13, 19, 12},
            {1, 9, 13},
            {1, 16, 0, 2, 10, 14},
            {1, 3, 11, 15},
            {1, 16},
            {1, 5, 17},
            {1, 9, 18},
            {1, 16, 18, 19},
            {1, 3, 20},
            {1, 3, 20, 21},
            {1, 3, 20, 22},
            {1, 9, 13, 15, 23},
        },
        {
            {2, 0},
            {2, 0, 16, 1},
            {2},
            {2, 20, 3},
            {2, 6, 4},
            {2, 0, 4, 17, 5},
            {2, 6},
            {2, 20, 3, 7},
            {2, 10, 8},
            {2, 0, 8, 18, 9},
            {2, 10},
            {2, 20, 3, 11},
            {2, 0, 8, 12},
            {2, 0, 16, 1, 9, 13},
            {2, 10, 14},
            {2, 10, 14, 23, 15},
            {2, 0, 16},
            {2, 0, 16, 17},
            {2, 0, 16, 18},
            {2, 10, 14, 12, 19},
            {2, 20},
            {2, 6, 21},
            {2, 10, 22},
            {2, 20, 22, 23},
        },
        {
            {3, 1, 16, 0},
            {3, 1},
            {3, 20, 2},
            {3},
            {3, 1, 5, 17, 4},
            {3, 7, 5},
            {3, 20, 2, 6},
            {3, 7},
            {3, 1, 9, 18, 8},
            {3, 11, 9},
            {3, 20, 2, 10},
            {3, 11},
            {3, 1, 16, 0, 8, 12},
            {3, 1, 9, 13},
            {3, 11, 15, 23, 14},
            {3, 11, 15},
            {3, 1, 16},
            {3, 1, 16, 17},
            {3, 1, 16, 18},
            {3, 11, 15, 13, 19},
            {3, 20},
            {3, 7, 21},
            {3, 11, 22},
            {3, 20, 22, 23},
        },
        {
            {4, 0},
            {4, 17, 5, 1},
            {4, 0, 2},
            {4, 17, 16, 1, 3},
            {4},
            {4, 17, 5},
            {4, 6},
            {4, 17, 5, 7},
            {4, 0, 8},
            {4, 0, 8, 18, 9},
            {4, 6, 2, 10},
            {4, 17, 5, 7, 3, 11},
            {4, 12},
            {4, 17, 5, 13},
            {4, 12, 14},
            {4, 17, 19, 13, 15},
            {4, 0, 16},
            {4, 17},
            {4, 17, 16, 18},
            {4, 12, 19},
            {4, 6, 21, 20},
            {4, 6, 21},
            {4, 0, 8, 10, 22},
            {4, 6, 21, 23},
        },
        {
            {5, 17, 4, 0},
            {5, 1},
            {5, 17, 16, 0, 2},
            {5, 1, 3},
            {5, 17, 4},
            {5},
            {5, 17, 4, 6},
            {5, 7},
            {5, 1, 9, 18, 8},
            {5, 1, 9},
            {5, 17, 4, 6, 2, 10},
            {5, 7, 15, 11},
            {5, 17, 4, 12},
            {5, 13},
            {5, 17, 19, 12, 14},
            {5, 13, 15},
            {5, 1, 16},
            {5, 17},
            {5, 17, 16, 18},
            {5, 13, 19},
            {5, 7, 21, 20},
            {5, 7, 21},
            {5, 1, 9, 11, 22},
            {5, 7, 21, 23},
        },
        {
            {6, 2, 0},
            {6, 4, 0, 16, 1},
            {6, 2},
            {6, 21, 7, 3},
            {6, 4},
            {6, 4, 17, 5},
            {6},
            {6, 21, 7},
            {6, 4, 0, 8},
            {6, 4, 17, 5, 1, 9},
            {6, 2, 10},
            {6, 2, 10, 22, 11},
            {6, 14, 12},
            {6, 4, 12, 19, 13},
            {6, 14},
            {6, 21, 7, 15},
            {6, 4, 17, 16},
            {6, 4, 17},
            {6, 2, 10, 8, 18},
            {6, 4, 17, 19},
            {6, 2, 20},
            {6, 21},
            {6, 21, 23, 22},
            {6, 14, 23},
        },
        {
            {7, 5, 1, 16, 0},
            {7, 3, 1},
            {7, 21, 6, 2},
            {7, 3},
            {7, 5, 17, 4},
            {7, 5},
            {7, 21, 6},
            {7},
            {7, 5, 17, 4, 0, 8},
            {7, 5, 1, 9},
            {7, 15, 11, 22, 10},
            {7, 3, 11},
            {7, 5, 13, 19, 12},
            {7, 15, 13},
            {7, 21, 6, 14},
            {7, 15},
            {7, 5, 17, 16},
            {7, 5, 17},
            {7, 15, 11, 9, 18},
            {7, 5, 17, 19},
            {7, 3, 20},
            {7, 21},
            {7, 21, 23, 22},
            {7, 15, 23},
        },
        {
            {8, 0},
            {8, 18, 9, 1},
            {8, 0, 2},
            {8, 18, 16, 1, 3},
            {8, 0, 4},
            {8, 0, 4, 17, 5},
            {8, 10, 2, 6},
            {8, 18, 9, 11, 15, 7},
            {8},
            {8, 18, 9},
            {8, 10},
            {8, 18, 9, 11},
            {8, 12},
            {8, 18, 9, 13},
            {8, 12, 14},
            {8, 18, 19, 13, 15},
            {8, 0, 16},
            {8, 18, 16, 17},
            {8, 18},
            {8, 12, 19},
            {8, 10, 22, 20},
            {8, 0, 4, 6, 21},
            {8, 10, 22},
            {8, 10, 22, 23},
        },
        {
            {9, 18, 8, 0},
            {9, 1},
            {9, 18, 16, 0, 2},
            {9, 1, 3},
            {9, 1, 5, 17, 4},
            {9, 1, 5},
            {9, 18, 8, 10, 2, 6},
            {9, 11, 3, 7},
            {9, 18, 8},
            {9},
            {9, 18, 8, 10},
            {9, 11},
            {9, 18, 8, 12},
            {9, 13},
            {9, 18, 19, 12, 14},
            {9, 13, 15},
            {9, 1, 16},
            {9, 18, 16, 17},
            {9, 18},
            {9, 13, 19},
            {9, 11, 22, 20},
            {9, 1, 5, 7, 21},
            {9, 11, 22},
            {9, 11, 22, 23},
        },
        {
            {10, 2, 0},
            {10, 8, 0, 16, 1},
            {10, 2},
            {10, 22, 11, 3},
            {10, 8, 0, 4},
            {10, 8, 18, 9, 1, 5},
            {10, 2, 6},
            {10, 2, 6, 21, 7},
            {10, 8},
            {10, 8, 18, 9},
            {10},
            {10, 22, 11},
            {10, 14, 12},
            {10, 8, 12, 19, 13},
            {10, 14},
            {10, 22, 11, 15},
            {10, 8, 18, 16},
            {10, 2, 6, 4, 17},
            {10, 8, 18},
            {10, 8, 18, 19},
            {10, 2, 20},
            {10, 22, 20, 21},
            {10, 22},
            {10, 14, 23},
        },
        {
            {11, 9, 1, 16, 0},
            {11, 3, 1},
            {11, 22, 10, 2},
            {11, 3},
            {11, 9, 18, 8, 0, 4},
            {11, 9, 1, 5},
            {11, 3, 7, 21, 6},
            {11, 15, 7},
            {11, 9, 18, 8},
            {11, 9},
            {11, 22, 10},
            {11},
            {11, 9, 13, 19, 12},
            {11, 15, 13},
            {11, 22, 10, 14},
            {11, 15},
            {11, 9, 18, 16},
            {11, 3, 7, 5, 17},
            {11, 9, 18},
            {11, 9, 18, 19},
            {11, 3, 20},
            {11, 22, 20, 21},
            {11, 22},
            {11, 15, 23},
        },
        {
            {12, 8, 0},
            {12, 8, 0, 16, 1},
            {12, 14, 10, 2},
            {12, 19, 13, 15, 11, 3},
            {12, 4},
            {12, 19, 13, 5},
            {12, 4, 6},
            {12, 19, 17, 5, 7},
            {12, 8},
            {12, 19, 13, 9},
            {12, 8, 10},
            {12, 19, 18, 9, 11},
            {12},
            {12, 19, 13},
            {12, 14},
            {12, 19, 13, 15},
            {12, 19, 18, 16},
            {12, 4, 17},
            {12, 8, 18},
            {12, 19},
            {12, 8, 0, 2, 20},
            {12, 14, 23, 21},
            {12, 14, 23, 22},
            {12, 14, 23},
        },
        {
            {13, 9, 1, 16, 0},
            {13, 9, 1},
            {13, 19, 12, 14, 10, 2},
            {13, 15, 11, 3},
            {13, 19, 12, 4},
            {13, 5},
            {13, 19, 17, 4, 6},
            {13, 5, 7},
            {13, 19, 12, 8},
            {13, 9},
            {13, 19, 18, 8, 10},
            {13, 9, 11},
            {13, 19, 12},
            {13},
            {13, 19, 12, 14},
            {13, 15},
            {13, 19, 18, 16},
            {13, 5, 17},
            {13, 9, 18},
            {13, 19},
            {13, 9, 1, 3, 20},
            {13, 15, 23, 21},
            {13, 15, 23, 22},
            {13, 15, 23},
        },
        {
            {14, 12, 8, 0},
            {14, 12, 19, 13, 9, 1},
            {14, 10, 2},
            {14, 10, 2, 20, 3},
            {14, 6, 4},
            {14, 12, 4, 17, 5},
            {14, 6},
            {14, 23, 15, 7},
            {14, 10, 8},
            {14, 12, 8, 18, 9},
            {14, 10},
            {14, 23, 15, 11},
            {14, 12},
            {14, 12, 19, 13},
            {14},
            {14, 23, 15},
            {14, 10, 2, 0, 16},
            {14, 12, 19, 17},
            {14, 12, 19, 18},
            {14, 12, 19},
            {14, 23, 22, 20},
            {14, 6, 21},
            {14, 10, 22},
            {14, 23},
        },
        {
            {15, 13, 19, 12, 8, 0},
            {15, 13, 9, 1},
            {15, 11, 3, 20, 2},
            {15, 11, 3},
            {15, 13, 5, 17, 4},
            {15, 7, 5},
            {15, 23, 14, 6},
            {15, 7},
            {15, 13, 9, 18, 8},
            {15, 11, 9},
            {15, 23, 14, 10},
            {15, 11},
            {15, 13, 19, 12},
            {15, 13},
            {15, 23, 14},
            {15},
            {15, 11, 3, 1, 16},
            {15, 13, 19, 17},
            {15, 13, 19, 18},
            {15, 13, 19},
            {15, 23, 22, 20},
            {15, 7, 21},
            {15, 11, 22},
            {15, 23},
        },
        {
            {16, 0},
            {16, 1},
            {16, 0, 2},
            {16, 1, 3},
            {16, 17, 4},
            {16, 17, 5},
            {16, 0, 2, 6},
            {16, 1, 3, 7},
            {16, 18, 8},
            {16, 18, 9},
            {16, 0, 2, 10},
            {16, 1, 3, 11},
            {16, 0, 8, 12},
            {16, 1, 9, 13},
            {16, 18, 19, 12, 14},
            {16, 18, 19, 13, 15},
            {16},
            {16, 17},
            {16, 18},
            {16, 18, 19},
            {16, 0, 2, 20},
            {16, 0, 4, 6, 21},
            {16, 0, 8, 10, 22},
            {16, 0, 2, 20, 22, 23},
        },
        {
            {17, 16, 0},
            {17, 16, 1},
            {17, 4, 6, 2},
            {17, 5, 7, 3},
            {17, 4},
            {17, 5},
            {17, 4, 6},
            {17, 5, 7},
            {17, 4, 0, 8},
            {17, 5, 1, 9},
            {17, 16, 18, 8, 10},
            {17, 16, 18, 9, 11},
            {17, 19, 12},
            {17, 19, 13},
            {17, 4, 6, 14},
            {17, 5, 7, 15},
            {17, 16},
            {17},
            {17, 16, 18},
            {17, 19},
            {17, 4, 0, 2, 20},
            {17, 4, 6, 21},
            {17, 4, 6, 21, 20, 22},
            {17, 4, 12, 14, 23},
        },
        {
            {18, 16, 0},
            {18, 16, 1},
            {18, 8, 10, 2},
            {18, 9, 11, 3},
            {18, 8, 0, 4},
            {18, 9, 1, 5},
            {18, 16, 17, 4, 6},
            {18, 16, 17, 5, 7},
            {18, 8},
            {18, 9},
            {18, 8, 10},
            {18, 9, 11},
            {18, 19, 12},
            {18, 19, 13},
            {18, 8, 10, 14},
            {18, 9, 11, 15},
            {18, 16},
            {18, 16, 17},
            {18},
            {18, 19},
            {18, 8, 0, 2, 20},
            {18, 8, 10, 22, 23, 21},
            {18, 8, 10, 22},
            {18, 8, 12, 14, 23},
        },
        {
            {19, 12, 8, 0},
            {19, 13, 9, 1},
            {19, 18, 16, 0, 2},
            {19, 18, 16, 1, 3},
            {19, 17, 4},
            {19, 17, 5},
            {19, 12, 14, 6},
            {19, 13, 15, 7},
            {19, 18, 8},
            {19, 18, 9},
            {19, 12, 14, 10},
            {19, 13, 15, 11},
            {19, 12},
            {19, 13},
            {19, 12, 14},
            {19, 13, 15},
            {19, 18, 16},
            {19, 17},
            {19, 18},
            {19},
            {19, 12, 14, 23, 22, 20},
            {19, 12, 4, 6, 21},
            {19, 12, 8, 10, 22},
            {19, 12, 14, 23},
        },
        {
            {20, 2, 0},
            {20, 3, 1},
            {20, 2},
            {20, 3},
            {20, 2, 0, 4},
            {20, 3, 1, 5},
            {20, 21, 6},
            {20, 21, 7},
            {20, 2, 0, 8},
            {20, 3, 1, 9},
            {20, 22, 10},
            {20, 22, 11},
            {20, 22, 23, 14, 12},
            {20, 22, 23, 15, 13},
            {20, 2, 10, 14},
            {20, 3, 11, 15},
            {20, 2, 0, 16},
            {20, 2, 6, 4, 17},
            {20, 2, 10, 8, 18},
            {20, 2, 0, 16, 18, 19},
            {20},
            {20, 21},
            {20, 22},
            {20, 22, 23},
        },
        {
            {21, 6, 4, 0},
            {21, 7, 5, 1},
            {21, 20, 2},
            {21, 20, 3},
            {21, 6, 4},
            {21, 7, 5},
            {21, 6},
            {21, 7},
            {21, 23, 22, 10, 8},
            {21, 23, 22, 11, 9},
            {21, 6, 2, 10},
            {21, 7, 15, 11},
            {21, 6, 4, 12},
            {21, 7, 5, 13},
            {21, 23, 14},
            {21, 23, 15},
            {21, 6, 2, 0, 16},
            {21, 6, 4, 17},
            {21, 6, 4, 17, 16, 18},
            {21, 6, 14, 12, 19},
            {21, 20},
            {21},
            {21, 20, 22},
            {21, 23},
        },
        {
            {22, 10, 8, 0},
            {22, 11, 9, 1},
            {22, 20, 2},
            {22, 20, 3},
            {22, 20, 21, 6, 4},
            {22, 20, 21, 7, 5},
            {22, 10, 2, 6},
            {22, 11, 3, 7},
            {22, 10, 8},
            {22, 11, 9},
            {22, 10},
            {22, 11},
            {22, 10, 8, 12},
            {22, 11, 9, 13},
            {22, 23, 14},
            {22, 23, 15},
            {22, 10, 2, 0, 16},
            {22, 10, 8, 18, 16, 17},
            {22, 10, 8, 18},
            {22, 10, 14, 12, 19},
            {22, 20},
            {22, 23, 21},
            {22},
            {22, 23},
        },
        {
            {23, 22, 20, 2, 0},
            {23, 22, 20, 3, 1},
            {23, 14, 10, 2},
            {23, 15, 11, 3},
            {23, 14, 12, 4},
            {23, 15, 13, 5},
            {23, 21, 6},
            {23, 21, 7},
            {23, 14, 12, 8},
            {23, 15, 13, 9},
            {23, 22, 10},
            {23, 22, 11},
            {23, 14, 12},
            {23, 15, 13},
            {23, 14},
            {23, 15},
            {23, 14, 12, 19, 18, 16},
            {23, 14, 6, 4, 17},
            {23, 14, 10, 8, 18},
            {23, 14, 12, 19},
            {23, 22, 20},
            {23, 21},
            {23, 22},
            {23},
        },
    };

    global_routing_table2 = routing_table;
}

void FoldedTorus::_ComputeSize(const Configuration &config) {
    inner_router_nubmers = 16;
    ports_per_inner_router = 4;
    side_router_nubmers = 8;
    ports_per_side_router = 6;

    mem_numbers = 16;

    _nodes = mem_numbers;                                             // 用于处理的node数量，这里是mem的数量
    _channels = 48;                                                   // router之间的的链路数量
    _size = inner_router_nubmers + side_router_nubmers + mem_numbers; // 所有节点的总数
}

void FoldedTorus::_BuildNet(const Configuration &config) {
    ostringstream router_name;

    // 实例化 Router 数组
    for (int node_item = 0; node_item < inner_router_nubmers + side_router_nubmers; node_item++) {
        router_name << "router";
        router_name << "_" << node_item;

        if (node_item < inner_router_nubmers) {
            _routers[node_item] = Router::NewRouter(config, this, router_name.str(), node_item, ports_per_inner_router, ports_per_inner_router);
        } else {
            _routers[node_item] = Router::NewRouter(config, this, router_name.str(), node_item, ports_per_side_router, ports_per_side_router);
        }
        _timed_modules.push_back(_routers[node_item]);
        router_name.str("");
    }

    // 每个 Router 互连
    for (int row = 0; row < router_id.size(); row++) {
        for (int col = 0; col < router_id[row].size(); col++) {
            for (int edge = 0; edge < ports_per_inner_router; edge++) {
                _routers[router_id[row][col]]->AddOutputChannel(
                    _chan[links_from_this_router[row * router_id[row].size() + col][edge]],
                    _chan_cred[links_from_this_router[row * router_id[row].size() + col][edge]]);

                _routers[router_id[row][col]]->AddInputChannel(
                    _chan[links_to_this_router[row * router_id[row].size() + col][edge]],
                    _chan_cred[links_to_this_router[row * router_id[row].size() + col][edge]]);
            }
        }
    }

    // 8个side_router分别与mem相连
    for (int i = 0; i < side_nodes.size(); i++) {
        _routers[side_nodes[i]]->AddInputChannel(_inject[2 * i], _inject_cred[2 * i]);
        _routers[side_nodes[i]]->AddOutputChannel(_eject[2 * i], _eject_cred[2 * i]);
        _routers[side_nodes[i]]->AddInputChannel(_inject[2 * i + 1], _inject_cred[2 * i + 1]);
        _routers[side_nodes[i]]->AddOutputChannel(_eject[2 * i + 1], _eject_cred[2 * i + 1]);
    }
}

void FoldedTorus::RegisterRoutingFunctions() {
    gRoutingFunctionMap["min_foldedtorus"] = &min_foldedtorus;
}

void min_foldedtorus(const Router *r, const Flit *f, int in_channel,
                     OutputSet *outputs, bool inject) {
    int vcBegin = 0, vcEnd = gNumVCs - 1;
    if (f->type == Flit::READ_REQUEST) {
        vcBegin = gReadReqBeginVC;
        vcEnd = gReadReqEndVC;
    } else if (f->type == Flit::WRITE_REQUEST) {
        vcBegin = gWriteReqBeginVC;
        vcEnd = gWriteReqEndVC;
    } else if (f->type == Flit::READ_REPLY) {
        vcBegin = gReadReplyBeginVC;
        vcEnd = gReadReplyEndVC;
    } else if (f->type == Flit::WRITE_REPLY) {
        vcBegin = gWriteReplyBeginVC;
        vcEnd = gWriteReplyEndVC;
    }

    int out_port = -1;
    int next_hop;

    if (!inject) {
        next_hop = global_routing_table2[f->src][f->dest][f->hops];
    }

    switch (r->GetID()) {
    case 0:
        if (next_hop == 2)
            out_port = 1;
        else if (next_hop == 16)
            out_port = 0;
        else if (next_hop == 4)
            out_port = 0;
        else if (next_hop == 8)
            out_port = 0;
        break;

    default:
        break;
    }

    outputs->Clear();

    outputs->AddRange(out_port, vcBegin, vcEnd);
}